
/*
 		 ____   _____     ____     ______    _ 
 		| ___| |__ __|   /____\   |  __  |  | |
 		||___    | |    ||    ||  | |  | |  | |
 		|__  |   | |    ||    ||  | |__| |  |_|
  		 __| |   | |    ||____||  |  ____|   _
	 	|____|   |_|     \____/   |_|       |_|


	This code from NGSA Renewed.
	Do not modify and distrybude this code without permssion!
	Check out LICENSE.txt before you have will modify this code.

	facebook.com/ZimmerModd1ng

*/

// Lens Distortion (FishEye)
#define LENS_DISTORTION 1 
float   LensDistortion=		0.3;

// Grain
#define NOISE 1
float   fGrainSaturation=	0.5; 
float   fGrainIntensity=	0.05;  

//Moviebars
#define MOVIEBARS 0
float MoviebarsOffset=		0.2;

//Sharpening
float sharpen_strength=		0.5;

//+++++++++++++++++++++++++++++
//external parameters, do not modify
//+++++++++++++++++++++++++++++
//keyboard controlled temporary variables (in some versions exists in the config file). Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
float4 tempF1; //0,1,2,3
float4 tempF2; //5,6,7,8
float4 tempF3; //9,0
//x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float4 ScreenSize;
//x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4 Timer;
//adaptation delta time for focusing
float FadeFactor;
//changes in range 0..1, 0 means that night time, 1 - day time
float	ENightDayFactor;
//transposed transform matrix view*projection and inverse of it
float4	MatrixVP[4];
float4	MatrixInverseVP[4];

//textures
texture2D texColor;
texture2D texDepth;
texture2D texNoise;

sampler2D SamplerColor = sampler_state
{
    Texture = <texColor>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = NONE;//NONE;
    AddressU = Clamp;
    AddressV = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerDepth = sampler_state
{
    Texture = <texDepth>;
    MinFilter = POINT;
    MagFilter = POINT;
    MipFilter = NONE;
    AddressU = Clamp;
    AddressV = Clamp;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
    Texture = <texNoise>;
    MinFilter = POINT;
    MagFilter = POINT;
    MipFilter = NONE;//NONE
    AddressU = Wrap;
    AddressV = Wrap;
    SRGBTexture=FALSE;
    MaxMipLevel=0;
    MipMapLodBias=0;
};

struct VS_OUTPUT_POST
{
    float4 vpos    : POSITION;
    float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST
{
    float3 pos     : POSITION;
    float2 txcoord : TEXCOORD0;
};

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST r)
{
	VS_OUTPUT_POST v;

	float4 pos=float4(r.pos.x,r.pos.y,r.pos.z,1.0);

	v.vpos=pos;
	v.txcoord.xy=r.txcoord.xy;

	return v;
}

float random(in float2 uv)
{
    float2 noise = (frac(sin(dot(uv , float2(12.9898,78.233) * 2.0)) * 43758.5453));
    return abs(noise.x + noise.y) * 0.5;
}

float2 barrelDistortion( float2 p, float2 amt )
{
    p = 2.0 * p - 1.0;

    float maxBarrelPower = sqrt(5.0);
    float radius = dot(p,p); //faster but doesn't match above accurately
    p *= pow(radius, maxBarrelPower * amt);

    return p * 0.5 + 0.5;
}

float2 brownConradyDistortion(float2 uv, float scalar)
{
    uv = (uv - 0.5 ) * 2.0;
    
    if( true )
    {
        float barrelDistortion1 = -0.02 * scalar; // K1 in text books
        float barrelDistortion2 = 0.0 * scalar; // K2 in text books

        float r2 = dot(uv,uv);
        uv *= 1.0 + barrelDistortion1 * r2 + barrelDistortion2 * r2 * r2;
    }
    
   return (uv / 2.0) + 0.5;
}

float3 blurSample(in float2 uv, in float2 xoff, in float2 yoff)
{
    float3 v11 = tex2D(SamplerColor, uv + xoff).rgb;
    float3 v12 = tex2D(SamplerColor, uv + yoff).rgb;
    float3 v21 = tex2D(SamplerColor, uv - xoff).rgb;
    float3 v22 = tex2D(SamplerColor, uv - yoff).rgb;
    return (v11 + v12 + v21 + v22 + 2.0 * tex2D(SamplerColor, uv).rgb) * 0.166667;
}

float3 edgeStrength(in float2 uv)
{
   	const float spread = 0.5;
        float2 psize = float2(ScreenSize.y,ScreenSize.y*ScreenSize.z);
 	float2 offset = psize;
    float2 up    = float2(0.0, offset.y) * spread;
    float2 right = float2(offset.x, 0.0) * spread;
    const float frad =  3.0;
    float3 v11 = blurSample(uv + up - right, 	right, up);
    float3 v12 = blurSample(uv + up, 			right, up);
    float3 v13 = blurSample(uv + up + right, 	right, up);
    
    float3 v21 = blurSample(uv - right, 		right, up);
    float3 v22 = blurSample(uv, 				right, up);
    float3 v23 = blurSample(uv + right, 		right, up);
    
    float3 v31 = blurSample(uv - up - right, 	right, up);
    float3 v32 = blurSample(uv - up, 			right, up);
    float3 v33 = blurSample(uv - up + right, 	right, up);
    
    float3 laplacian_of_g = v11 * 0.0 + v12 *  1.0 + v13 * 0.0
        				+ v21 * 1.0 + v22 * -4.0 + v23 * 1.0
        				+ v31 * 0.0 + v32 *  1.0 + v33 * 0.0;
   		 laplacian_of_g = laplacian_of_g * 1.0;
    return laplacian_of_g.xyz;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

		float xy=3.0;																	float ZIMMER=1.0;																						float r=0.5;

float4 PS_fxaa(VS_OUTPUT_POST i) : COLOR
{

	float2 rcpFrame = float2(1/ScreenSize.x, 1/(ScreenSize.x/ScreenSize.z));
	float4 posPos;posPos.xy = i.txcoord.xy;posPos.zw = posPos.xy - (rcpFrame.xy * (.5 + .12));
	float3 rgbNW = tex2D(SamplerColor, posPos.zw ).xyz;float3 rgbNE = tex2D(SamplerColor, posPos.zw + float2(rcpFrame.x, 0.)).xyz;float3 rgbSW = tex2D(SamplerColor, posPos.zw + float2(0., rcpFrame.y)).xyz;float3 rgbSE = tex2D(SamplerColor, posPos.zw +rcpFrame.xy ).xyz;float3 rgbM  = tex2D(SamplerColor, posPos.xy).xyz;
	float3 luma = float3(.299, .587, .114);float lumaNW = dot(rgbNW, luma);float lumaNE = dot(rgbNE, luma);float lumaSW = dot(rgbSW, luma);float lumaSE = dot(rgbSE, luma);float lumaM = dot(rgbM, luma);
	float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
	float2 dir; 
	float lumaNWNE = lumaNW + lumaNE;float lumaSWSE = lumaSW + lumaSE;
	dir.x = -((lumaNWNE) - (lumaSWSE));dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
	float dirReduce = max( (lumaSWSE + lumaNWNE) * (.25 * .13), .15);float rcpDirMin = ZIMMER/(min(abs(dir.x), abs(dir.y)) + dirReduce);dir = min(4, max(-4, dir * rcpDirMin)) * rcpFrame.xy;
	float3 rgbA = (ZIMMER/2.) * (tex2D(SamplerColor, posPos.xy + dir * (ZIMMER/3. - .5)).xyz + tex2D(SamplerColor, posPos.xy + dir * (2./3. - .5)).xyz);float3 rgbB = rgbA * (ZIMMER/2.) + (ZIMMER/4.) * (tex2D(SamplerColor, posPos.xy + dir * (0./3. - .5)).xyz + tex2D(SamplerColor, posPos.xy + dir * (3./3. - .5)).xyz);float lumaB = dot(rgbB, luma);
	if((lumaB < lumaMin) || (lumaB > lumaMax))
	return float4(rgbA, 1);
	return float4(rgbB, 1);
}

float4 PS_sharp(VS_OUTPUT_POST d) : COLOR
{
	float2 uv = d.txcoord.xy;
	float4 fragColor;
    	fragColor = float4(tex2D(SamplerColor, uv).xyz - edgeStrength(uv) * sharpen_strength, 1.0);
	return fragColor;
}



float4 PS_FishEye(VS_OUTPUT_POST o) : COLOR
{
	float2 uv = o.txcoord.xy;
	float4 fragColor = 0.0;

    #if (LENS_DISTORTION == 1)
    float maxDistort = LensDistortion;

    float4 colourScalar = float4(700.0, 560.0, 490.0, 1.0);	// Based on the true wavelengths of red, green, blue light.
    colourScalar /= max(max(colourScalar.x, colourScalar.y), colourScalar.z);
    colourScalar *= 2.0;

    colourScalar *= maxDistort;

    const float numTaps = 8.0;
    
    
    for( float tap = 0.0; tap < numTaps; tap += 1.0 )
    {
        fragColor.r += tex2D(SamplerColor, brownConradyDistortion(uv, colourScalar.r)).r;
        fragColor.g += tex2D(SamplerColor, brownConradyDistortion(uv, colourScalar.g)).g;
        fragColor.b += tex2D(SamplerColor, brownConradyDistortion(uv, colourScalar.b)).b;
        
        colourScalar *= 0.95;
    }
    
    fragColor /= numTaps;

    fragColor.a = 1.0;

    #else
    fragColor = tex2D(SamplerColor, o.txcoord.xy);
    #endif

    return fragColor;
}

float4 PS_Effects(VS_OUTPUT_POST x) : COLOR
{
	float4 r = tex2D(SamplerColor, x.txcoord.xy);
	#if (NOISE == 1)
	float GrainTimerSeed = Timer.x * 1.6784738;
	float2 GrainTexCoordSeed = x.txcoord.xy * 1.;
	float2 GrainSeed1 = GrainTexCoordSeed + float2(0., GrainTimerSeed);
	float2 GrainSeed2 = GrainTexCoordSeed + float2(GrainTimerSeed, 0.);
	float2 GrainSeed3 = GrainTexCoordSeed + float2(GrainTimerSeed, GrainTimerSeed);
	float GrainNoise1 = random(GrainSeed1);
	float GrainNoise2 = random(GrainSeed2);
	float GrainNoise3 = random(GrainSeed3);
	float GrainNoise4 = (GrainNoise1 + GrainNoise2 + GrainNoise3) * .333333333;
	float3 GrainNoise = float3(GrainNoise4, GrainNoise4, GrainNoise4 );
	float3 GrainColor = float3(GrainNoise1, GrainNoise2, GrainNoise3 );
	r.rgb += (lerp(GrainNoise, GrainColor, fGrainSaturation ) * fGrainIntensity ) - (fGrainIntensity * .5);
	#endif

	#if (MOVIEBARS == 1)
	float offset = MoviebarsOffset * .5;
	if (x.txcoord.y <= offset || x.txcoord.y >= (1. - offset)) r.xyzw = 0.;
	#endif

	r.w=1.;
	return r;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

technique PostProcess
{
  pass p0
  {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_fxaa();
  }
}

technique PostProcess2  
{
  pass p0
  {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_sharp();
  }
}


technique PostProcess3  
{
  pass p0
  {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_FishEye();
  }
}

technique PostProcess4  
{
  pass p0
  {
	VertexShader = compile vs_3_0 VS_PostProcess();
	PixelShader  = compile ps_3_0 PS_Effects();
  }
}


